import pygame                   # 导入pygame库
from pygame.locals import *     # 导入pygame库中的一些常量
import sys
import time
import random

class Airplane():
    def __init__(self,screen_temp):
        self.screen = screen_temp
        self.plane_img = pygame.image.load('./images/airplane.png')  # 导入飞机图片
        self.hero1_rect = pygame.Rect(0, 0, 80, 113)  # left,right,top,bottom
        self.hero2_rect = pygame.Rect(0, 0, 80, 90)
        self.hero1 = self.plane_img.subsurface(self.hero1_rect)
        self.hero2 = self.plane_img.subsurface(self.hero2_rect)
        self.life = 3    # 飞机生命值
        self.x = 200     # 飞机横坐标
        self.y = 200     # 飞机纵坐标
        self.bullet_list = []                 # 用来存储子弹对象的引用
        #爆炸效果属性
        self.hit = False        #设置是否要爆炸效果
        self.bomb_list =[]      #存储爆炸时需要的图片
        self.__create_images()  #添加爆炸图片
        self.image_num = 0      #用来记录while True的次数,当次数达到一定值时才显示一张爆炸的图,然后清空,,当这个次数再次达到时,再显示下一个爆炸效果的图片
        self.image_index = 0    #记录当前要显示的爆炸图片序号

    def __create_images(self):
        # 添加爆炸图片
        self.bomb_list.append(pygame.image.load("./images/blowup1.png"))

    def move(self,move_x,move_y):
        self.x += move_x
        self.y += move_y

    def bomb(self):
        self.hit = True

    def judge(self):
        if self.life <= 0:
            self.bomb()

    def display(self):
        # 显示玩家的飞机
        # 如果被击中,就显示爆炸效果,否则显示普通的飞机效果
        if self.hit == True:
            # blit方法 （一个对象，左上角位置）,# (self.x, self.y)是指当前飞机的位置
            self.screen.blit(self.bomb_list[self.image_index], (self.x, self.y))
            self.image_num += 1
            print(self.image_num)
            if  self.image_num == 7:
                self.image_num = 0
                self.image_index += 1
                print(self.image_index)  # 这里子弹打住飞机时没有被清除掉，所以打一下，就死了
            if self.image_index > 3:
                time.sleep(1)
                exit()                   # 死了3次后，调用exit让游戏退出
        # 控制英雄，不让它跑出界面
        else:
            if self.x < 0:
                self.x = 0
            elif self.x > width - self.hero1_rect.width:
                self.x = width - self.hero1_rect.width
            if self.y < 0:
                self.y = 0
            elif self.y > height - self.hero1_rect.height:
                self.y = height - self.hero1_rect.height

        # 不管玩家飞机是否被击中,都要显示发射出去的子弹
        for bullet1 in self.bullet_list:
            bullet1.display()
            bullet1.move()

    def fire(self):
        bullet1 = Bullet(self.screen,self.x,self.y)
        self.bullet_list.append(bullet1)


class Bullet(object):
    def __init__(self,screen_temp,x_temp,y_temp):
        self.screen = screen_temp
        self.image = pygame.image.load('./images/bullet1.png')
        self.x = x_temp + 36       # 调整子弹与飞机的横向距离
        self.y = y_temp - 20       # 调整子弹与飞机的竖向距离

    def display(self):
        self.screen.blit(self.image,(self.x,self.y))

    def move(self):
        self.y -= 15      #子两个子弹间的间距，值越大，间距越大



class Bullet_Enemy():
    #敌机子弹类
    def __init__(self, screen_temp, x_temp, y_temp):
        self.life = 10
        self.x = x_temp + 7    # 控制敌机子弹与敌机横向距离
        self.y = y_temp + 20    # 控制敌机子弹与敌机竖向距离
        self.image = pygame.image.load("./images/bullet1.png")
        self.screen = screen_temp

    def display(self):
        self.screen.blit(self.image,(self.x,self.y))

    def move(self, plane):
        self.y += 10
        if (plane.y <= self.y and self.y <= plane.y + 40) and (plane.x <= self.x and self.x <= plane.x + 100):
        #if self.y in range(hero.y, hero.y + 40) and self.x in range(hero.x, hero.x + 40):
            self.life -= 10
            #self.bullet_list.remove()
            print("---judge_enemy---")
            return True


class EnemyPlane():
    #敌机类
    def __init__(self, screen_temp):
        self.x = random.randint(15, 430)      #横坐标随机位置生成敌机
        self.y = 0
        self.image = pygame.image.load("./images/enemy0.png")
        self.screen = screen_temp
        self.bullet_list = []#用来存储子弹对象的引用
        #self.direction = "right"#用来设置这个飞机默认的移动方向
        self.hit = False
        self.bomb_list = []
        self.__create_images()
        self.image_num = 0
        self.image_index = 0
        #利用随机数，生成敌机初始移动方向
        self.k = random.randint(1, 20)
        if self.k <= 10:
            self.direction = "right"
        elif self.k > 10:
            self.direction = "left"

    def display(self, plane):
        #显示敌人的飞机
        if not self.hit:
            self.screen.blit(self.image, (self.x,self.y))
        else:
            self.screen.blit(self.bomb_list[self.image_index], (self.x,self.y))
            self.image_num += 1
            if self.image_num == 3 and self.image_index < 3:
                self.image_num = 0
                self.image_index += 1
                #print(self.image_index)
            # if self.image_index > 2:
            #     time.sleep(0.1)

        for bullet in self.bullet_list:
            bullet.display()
            if(bullet.move(plane)):
                self.bullet_list.remove(bullet)

    def fire(self):
        #利用随机数来控制敌机的开火，右边值越大，子弹发射速度越慢
        s = random.randint(0,200)
        bullet1 = Bullet_Enemy(self.screen, self.x, self.y)
        if s < 10:
            self.bullet_list.append(bullet1)

    def move(self):
        #利用随机数来控制飞机移动距离，以及移动范围
        d1 = random.uniform(1,3)
        d2 = random.uniform(0.2,3)
        p1 = random.uniform(50,100)
        p2 = random.uniform(-100,0)
        if self.direction == "right":
            self.x += d1
        elif self.direction == "left":
            self.x -= d1

        if self.x > width - p1:
            self.direction="left"
        elif self.x < p2:
            self.direction = "right"
        self.y += d2

    def bomb(self):
        self.hit = True

    def __create_images(self):
        self.bomb_list.append(pygame.image.load("./images/enemy0_down1.png"))


class EnemyPlanes(EnemyPlane):
    #敌机群类  继承自EnemyPlane类
    def __init__(self, screen_temp):
        EnemyPlane.__init__(self, screen_temp)
        self.num = 0
        self.enemy_list = []        #用列表存储产生的多架敌机
        self.screen = screen_temp

    def add_enemy(self, num):
    #产生多架敌机的函数
        self.num = num
        for i in range(num):
            enemy = EnemyPlane(self.screen)
            self.enemy_list.append(enemy)

    def display(self, plane):
        for i in range(self.num):
            self.enemy_list[i].display(plane)

    def move(self):
        for i in range(self.num):
            self.enemy_list[i].move()

    def fire(self):
        #s = random.randint(0,1000)
        for i in range(self.num):
            self.enemy_list[i].fire()


def main():
    FRAME_RATE = 60         # 定义画面帧率
    ANIMATE_CYCLE = 30      # 定义动画周期（帧数）
    ticks = 0               # 为了飞机动态效果设置一个变量
    pygame.init()           # 初始化pygame
    screen = pygame.display.set_mode(size)  # 初始化游戏窗口
    pygame.display.set_caption("my first pygame program")      # 设置游戏窗口标题
    background = pygame.image.load('./images/background.jpg')  # 设置游戏窗口背景图片
    clock = pygame.time.Clock()  # 创建一个记录时间的对象
    left_key, right_key, up_key, down_key, done = 0, 0, 0, 0, 0
    plane = Airplane(screen)
    move_x =0
    move_y =0
    enemis = EnemyPlanes(screen)
    enemis.add_enemy(5)



    while True:
        clock.tick(FRAME_RATE)
        screen.blit(background, (0, 0))         # 绘制背景图片
        # 控制飞机的喷射效果
        if ticks % FRAME_RATE < ANIMATE_CYCLE:
            screen.blit(plane.hero1, (plane.x,plane.y))
        else:
            screen.blit(plane.hero2, (plane.x,plane.y))
        ticks += 1

        if done:
            if done % 8 == 0:             #长按空格键时控制子弹发射的速度，值越大，越慢
                done = 1
                plane.fire()
            else:
                done += 1

        for event in pygame.event.get():
            if event.type == pygame.QUIT:     #判断是否按了退出键
                pygame.quit()
                sys.exit()

            if event.type == pygame.KEYDOWN:
                if event.key == K_a or event.key == K_LEFT:   # 判断是否鼠标按了下键（a或者left）
                    move_x = -5
                    left_key += 1
                elif event.key == K_d or event.key == K_RIGHT:  # 检测按键是否是d或者right
                    move_x = 5
                    right_key += 1

                elif event.key == K_w or event.key == K_UP:    #w或者上键
                    move_y = -5
                    up_key += 1
                elif event.key == K_s or event.key == K_DOWN:   #s或者下键
                    move_y = 5
                    down_key += 1

                elif event.key == K_SPACE:                      #按一次空格键done加1
                    plane.fire()
                    done = 1                                    #确保长按空格键的时候子弹一直发射

                elif event.key == K_b:
                    print('b')
                    plane.bomb()


            if event.type == pygame.KEYUP:                     # 鼠标松开
                if event.key == K_a or event.key == K_LEFT:
                    left_key -= 1
                    if right_key == 0:
                        move_x = 0
                    else:
                        move_x = 5

                if event.key == K_d or event.key == K_RIGHT:
                    right_key -= 1
                    if left_key == 0:
                        move_x = 0
                    else:
                        move_x = -5

                if event.key == K_w or event.key == K_UP:
                    up_key -= 1
                    if down_key == 0:
                        move_y = 0
                    else:
                        move_y = 5

                if event.key == K_s or event.key == K_DOWN:
                    down_key -= 1
                    if up_key == 0:
                        move_y = 0
                    else:
                        move_y = -5

                if event.key == K_SPACE:  #松开空格键，done变成0，子弹不发射
                    done = 0              #如果要让飞机自动发射子弹，可以将done设为8，按一次空格后放开一直发射

        plane.move(move_x,move_y)
        plane.display()

        n = random.randint(1, 5)
        enemis.display(plane)
        enemis.move()
        enemis.fire()



        pygame.display.update()



if __name__ == "__main__":
    size = width, height = 454, 340  # 设置游戏窗口大小，宽454，高340
    main()



